package com.gobang.common.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gobang.common.exception.ErrorCode;
import com.gobang.domain.message.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 消息处理工具类
 * 提供WebSocket消息的序列化、反序列化和构造方法
 * 
 * @author System
 * @since 1.0.0
 */
@Component
@Slf4j
public class MessageUtils {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 将消息对象序列化为JSON字符串
     *
     * @param message 消息对象
     * @return JSON字符串
     */
    public static String toJson(WebSocketMessage message) {
        try {
            return objectMapper.writeValueAsString(message);
        } catch (JsonProcessingException e) {
            log.error("消息序列化失败", e);
            return null;
        }
    }
    
    /**
     * 将JSON字符串反序列化为消息对象
     *
     * @param json JSON字符串
     * @param clazz 目标类型
     * @return 消息对象
     */
    public static <T extends WebSocketMessage> T fromJson(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            log.error("消息反序列化失败: {}", json, e);
            return null;
        }
    }
    
    /**
     * 创建心跳消息
     *
     * @return 心跳消息
     */
    public static HeartbeatMessage createHeartbeatMessage() {
        return HeartbeatMessage.create();
    }
    
    /**
     * 创建错误响应消息
     *
     * @param errorCode 错误码
     * @param errorMessage 错误消息
     * @return 错误响应消息
     */
    public static ErrorResponseMessage createErrorMessage(ErrorCode errorCode, String errorMessage) {
        ErrorResponseMessage.ErrorResponseData data = ErrorResponseMessage.ErrorResponseData.builder()
                .errorCode(errorCode.getCode())
                .errorMessage(errorMessage != null ? errorMessage : errorCode.getMessage())
                .build();
        return new ErrorResponseMessage(data);
    }
    
    /**
     * 创建落子响应消息（成功）
     *
     * @param roomId 房间ID
     * @param row 行坐标
     * @param col 列坐标
     * @param color 棋子颜色
     * @param gameStatus 游戏状态
     * @param nextTurn 下一轮
     * @param isGameOver 是否游戏结束
     * @param winnerId 获胜者ID
     * @return 落子响应消息
     */
    public static MoveResponseMessage createSuccessMoveResponse(String roomId, Integer row, Integer col,
                                                                String color, String gameStatus, String nextTurn,
                                                                Boolean isGameOver, Long winnerId) {
        MoveResponseMessage.MoveInfo moveInfo = MoveResponseMessage.MoveInfo.builder()
                .row(row)
                .col(col)
                .color(color)
                .build();
        
        MoveResponseMessage.MoveResponseData data = MoveResponseMessage.MoveResponseData.builder()
                .roomId(roomId)
                .success(true)
                .move(moveInfo)
                .gameStatus(gameStatus)
                .nextTurn(nextTurn)
                .isGameOver(isGameOver)
                .winnerId(winnerId)
                .build();
        
        return new MoveResponseMessage(data);
    }
    
    /**
     * 创建落子响应消息（失败）
     *
     * @param roomId 房间ID
     * @param errorCode 错误码
     * @param errorMessage 错误消息
     * @param nextTurn 下一轮
     * @return 落子响应消息
     */
    public static MoveResponseMessage createFailedMoveResponse(String roomId, String errorCode, 
                                                              String errorMessage, String nextTurn) {
        MoveResponseMessage.MoveResponseData data = MoveResponseMessage.MoveResponseData.builder()
                .roomId(roomId)
                .success(false)
                .move(null)
                .gameStatus("PLAYING")
                .nextTurn(nextTurn)
                .isGameOver(false)
                .winnerId(null)
                .errorCode(errorCode)
                .errorMessage(errorMessage)
                .build();
        
        return new MoveResponseMessage(data);
    }
    
    /**
     * 创建游戏状态更新消息
     *
     * @param roomId 房间ID
     * @param currentTurn 当前轮到谁
     * @param moveCount 步数
     * @param gameStatus 游戏状态
     * @param lastRow 最后一步行坐标
     * @param lastCol 最后一步列坐标
     * @param lastColor 最后一步颜色
     * @param boardState 棋盘状态
     * @return 游戏状态更新消息
     */
    public static GameStateUpdateMessage createGameStateUpdateMessage(String roomId, String currentTurn, 
                                                                     Integer moveCount, String gameStatus,
                                                                     Integer lastRow, Integer lastCol, String lastColor,
                                                                     int[][] boardState) {
        GameStateUpdateMessage.LastMoveInfo lastMove = null;
        if (lastRow != null && lastCol != null && lastColor != null) {
            lastMove = GameStateUpdateMessage.LastMoveInfo.builder()
                    .row(lastRow)
                    .col(lastCol)
                    .color(lastColor)
                    .build();
        }
        
        GameStateUpdateMessage.GameStateUpdateData data = GameStateUpdateMessage.GameStateUpdateData.builder()
                .roomId(roomId)
                .currentTurn(currentTurn)
                .lastMove(lastMove)
                .moveCount(moveCount)
                .gameStatus(gameStatus)
                .boardState(boardState)
                .build();
        
        return new GameStateUpdateMessage(data);
    }
    
    /**
     * 创建匹配状态更新消息
     *
     * @param status 匹配状态
     * @param waitTime 等待时间
     * @param queuePosition 队列位置
     * @return 匹配状态更新消息
     */
    public static MatchStatusUpdateMessage createMatchStatusUpdateMessage(String status, Integer waitTime,
                                                                          Integer queuePosition) {
        MatchStatusUpdateMessage.MatchStatusUpdateData data = MatchStatusUpdateMessage.MatchStatusUpdateData.builder()
                .status(status)
                .waitTime(waitTime)
                .queuePosition(queuePosition)
                .build();
        
        return new MatchStatusUpdateMessage(data);
    }
    
    /**
     * 创建游戏结束消息
     *
     * @param roomId 房间ID
     * @param winnerId 获胜者ID
     * @param winnerUsername 获胜者用户名
     * @param gameResult 游戏结果
     * @param scoreChange 积分变化
     * @param newScore 新积分
     * @param reason 结束原因
     * @return 游戏结束消息
     */
    public static GameOverMessage createGameOverMessage(String roomId, Long winnerId, String winnerUsername,
                                                       String gameResult, Integer scoreChange, Integer newScore,
                                                       String reason) {
        GameOverMessage.GameOverData data = GameOverMessage.GameOverData.builder()
                .roomId(roomId)
                .winnerId(winnerId)
                .winnerUsername(winnerUsername)
                .gameResult(gameResult)
                .scoreChange(scoreChange)
                .newScore(newScore)
                .reason(reason)
                .build();
        
        return new GameOverMessage(data);
    }
    
    /**
     * 创建对手离线消息
     *
     * @param roomId 房间ID
     * @param opponentId 对手ID
     * @param opponentUsername 对手用户名
     * @param waitTime 等待时间
     * @return 对手离线消息
     */
    public static OpponentOfflineMessage createOpponentOfflineMessage(String roomId, Long opponentId,
                                                                      String opponentUsername, Integer waitTime) {
        OpponentOfflineMessage.OpponentOfflineData data = OpponentOfflineMessage.OpponentOfflineData.builder()
                .roomId(roomId)
                .opponentId(opponentId)
                .opponentUsername(opponentUsername)
                .waitTime(waitTime)
                .build();
        
        return new OpponentOfflineMessage(data);
    }
} 